﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Microsoft.SharePoint;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.Utilities;
using System.Web;

namespace Macaw.Moss2007.ContentChangesOverviewSolution
{
    public class RetrievedChangeInfo
    {
        public string objectUrl;
        public string objectTitle;
        public string user;
    }

    public class SPChangeHelper
    {

        /// <summary>
        /// This helper method tries to fetch the Url from a the NonPublic Array-field.
        /// This information is unfortunatly not available through the API.
        /// </summary>
        /// <param name="change">The Change to fetch the ObjectUrl of</param>
        /// <returns>The Url of the object  or  NULL</returns>
        private static string GetHiddenObjectUrl(SPChange change)
        {
            FieldInfo m_row_field = typeof(SPChange).GetField("m_row", BindingFlags.NonPublic | BindingFlags.Instance);
            if (m_row_field != null)
            {
                object[] m_row = (object[])m_row_field.GetValue(change);
                if (m_row.Length != 15) return null;
                if (m_row[10] is DBNull) return null;
                return (string)m_row[10];
            }
            return null;
        }

        private static string GetChangeUser(SPChange change, SPWeb web)
        {
            string user = string.Empty;

            if (web.Created.Equals(change.Time))
            {
                user = web.Author.Name + " (Created)";
                return user;
            }

            DateTime dtModified = (DateTime)web.RootFolder.Properties["vti_timelastmodified"];
            if (dtModified.Equals(change.Time))
            {
                if (!string.IsNullOrEmpty((string)web.RootFolder.Properties["vti_modifiedby"]))
                {
                    user = (string)web.RootFolder.Properties["vti_modifiedby"] + " (Modified)";
                    return user;
                }
            }

            return user;
        }

        private static string GetChangeUser(SPChange change, SPList list)
        {
            string user = string.Empty;

            if (list.Created.Equals(change.Time))
            {
                user = list.Author.Name + " (Created)";
                return user;
            }

            if (list.RootFolder != null)
            {
                user = GetChangeUser(change, list.RootFolder);
            }
            return user;
        }

        private static string GetChangeUser(SPChange change, SPFolder folder)
        {
            string user = string.Empty;

            DateTime dtModified = (DateTime)folder.Properties["vti_timelastmodified"];
            if (dtModified.Equals(change.Time))
            {
                if (!string.IsNullOrEmpty((string)folder.Properties["vti_modifiedby"]))
                {
                    user = (string)folder.Properties["vti_modifiedby"] + " (Modified)";
                    return user;
                }
            }


            try
            {
                if (folder.Item != null)
                {
                    user = GetChangeUser(change, folder.Item);
                }
            }
            catch
            {
                // folder.Item might throw an Exception
            }

            return user;
        }


        private static string GetChangeUser(SPChange change, SPFile file)
        {
            string user = string.Empty;


            foreach (SPFileVersion version in file.Versions)
            {
                if (version.Created.CompareTo(change.Time) == 0)
                {
                    user = version.CreatedBy.Name + " (" + version.Level.ToString() + " " + version.VersionLabel + ")";
                    return user;
                }
            }

            if (file != null)
            {
                if (file.TimeCreated.Equals(change.Time))
                {
                    if (file.Author != null)
                    {
                        user = file.Author.Name + " (Created)";
                        return user;
                    }
                }

                if (file.TimeLastModified.Equals(change.Time))
                {
                    if (file.ModifiedBy != null)
                    {
                        user = file.ModifiedBy.Name + " (Modified)";
                        return user;
                    }
                }
            }

            if (file.Item != null)
            {
                user = GetChangeUser(change, file.Item);
            }

            return user;
        }

        private static string GetChangeUser(SPChange change, SPListItem listitem)
        {
            string user = string.Empty;

            if (listitem.ParentList.EnableVersioning)
            {
                foreach (SPListItemVersion version in listitem.Versions)
                {
                    if (version.Created.CompareTo(change.Time) == 0)
                    {
                        user = version.CreatedBy.LookupValue + " (" + version.Level.ToString() + " " + version.VersionLabel + ")";
                        return user;
                    }
                }
            }
            if (listitem.File != null)
            {
                if (listitem.File.TimeCreated.Equals(change.Time))
                {
                    user = listitem.File.Author.Name + " (Created)";
                    return user;
                }


                if (listitem.File.TimeLastModified.Equals(change.Time))
                {
                    user = listitem.File.ModifiedBy.Name + " (Modified)";
                    return user;
                }

            }
            return user;
        }

        /// <summary>
        /// This method retrieves information of the SPChange and updates the controls
        /// </summary>
        /// <param name="change"></param>
        /// <param name="site"></param>
        /// <param name="hlItem"></param>
        public static RetrievedChangeInfo GetChangeInfo(SPChange change, SPSite site)
        {
            RetrievedChangeInfo changeinfo = new RetrievedChangeInfo();
            if (change is SPChangeFolder)
            {
                try
                {
                    SPChangeFolder _change = (SPChangeFolder)change;
                    using (SPWeb web = site.OpenWeb(_change.WebId))
                    {
                        try
                        {
                            SPFolder folder = web.GetFolder(_change.UniqueId);
                            changeinfo.objectTitle = folder.Name;
                            changeinfo.objectUrl = folder.ServerRelativeUrl;
                            changeinfo.user = GetChangeUser(change, folder);
                        }
                        catch
                        {
                            string hiddenObjectUrl = GetHiddenObjectUrl(change);
                            if (!string.IsNullOrEmpty(hiddenObjectUrl))
                            {
                                changeinfo.objectTitle = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, hiddenObjectUrl);
                                changeinfo.objectUrl = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, hiddenObjectUrl);
                            }
                        }
                    }
                }
                catch
                {
                    string hiddenObjectUrl = GetHiddenObjectUrl(change);
                    if (!string.IsNullOrEmpty(hiddenObjectUrl))
                    {
                        changeinfo.objectTitle = hiddenObjectUrl;
                        changeinfo.objectUrl = hiddenObjectUrl;
                    }
                }
            }
            else if (change is SPChangeView)
            {
                try
                {
                    SPChangeView _change = (SPChangeView)change;
                    using (SPWeb web = site.OpenWeb(_change.WebId))
                    {
                        SPList list = web.Lists[_change.ListId];
                        SPView view = list.Views[_change.Id];
                        changeinfo.objectTitle = view.Title;
                        changeinfo.objectUrl = view.ServerRelativeUrl;
                    }
                }
                catch
                {
                    string hiddenObjectUrl = GetHiddenObjectUrl(change);
                    if (!string.IsNullOrEmpty(hiddenObjectUrl))
                    {
                        changeinfo.objectTitle = hiddenObjectUrl;
                        changeinfo.objectUrl = hiddenObjectUrl;
                    }
                }
            }
            else if (change is SPChangeFile)
            {
                try
                {
                    SPChangeFile _change = (SPChangeFile)change;
                    using (SPWeb web = site.OpenWeb(_change.WebId))
                    {
                        try
                        {
                            SPFile file = web.GetFile(_change.UniqueId);
                            changeinfo.objectTitle = file.Name;
                            changeinfo.objectUrl = file.ServerRelativeUrl;
                            changeinfo.user = GetChangeUser(change, file);
                        }
                        catch
                        {
                            string hiddenObjectUrl = GetHiddenObjectUrl(change);
                            if (!string.IsNullOrEmpty(hiddenObjectUrl))
                            {
                                changeinfo.objectTitle = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, hiddenObjectUrl);
                                changeinfo.objectUrl = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, hiddenObjectUrl);
                            }
                        }
                    }
                }
                catch
                {
                    string hiddenObjectUrl = GetHiddenObjectUrl(change);
                    if (!string.IsNullOrEmpty(hiddenObjectUrl))
                    {
                        changeinfo.objectTitle = hiddenObjectUrl;
                        changeinfo.objectUrl = hiddenObjectUrl;
                    }
                }
            }
            else if (change is SPChangeGroup)
            {
                try
                {
                    SPChangeGroup _change = (SPChangeGroup)change;

                    using (SPWeb web = site.OpenWeb())
                    {

                        SPGroup group = web.Groups.GetByID(_change.Id);
                        changeinfo.objectTitle = group.Name;
                        changeinfo.objectUrl = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, "/_layouts/people.aspx?MembershipGroupId=" + group.ID);
                    }
                }
                catch
                {
                }
            }
            else if (change is SPChangeField)
            {
                try
                {
                    SPChangeField _change = (SPChangeField)change;

                    using (SPWeb web = site.OpenWeb(_change.WebId))
                    {
                        SPField field = web.Fields[_change.Id];
                        changeinfo.objectTitle = field.Title;
                        changeinfo.objectUrl = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, "/_layouts/fldedit.aspx?field=" + field.InternalName);
                    }
                }
                catch
                {
                }
            }
            else if (change is SPChangeUser)
            {
                try
                {
                    SPChangeUser _change = (SPChangeUser)change;

                    using (SPWeb web = site.OpenWeb())
                    {
                        SPUser user = web.AllUsers.GetByID(_change.Id);
                        changeinfo.objectTitle = user.Name;
                        changeinfo.objectUrl = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, "/_layouts/userdisp.aspx?ID=" + user.ID.ToString());
                    }
                }
                catch
                {
                }

            }
            else if (change is SPChangeContentType)
            {
                try
                {
                    SPChangeContentType _change = (SPChangeContentType)change;
                    using (SPWeb web = site.OpenWeb(_change.WebId))
                    {
                        SPContentType contenttype = web.ContentTypes[_change.Id];
                        changeinfo.objectTitle = contenttype.Name;
                        changeinfo.objectUrl = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, "/_layouts/ManageContentType.aspx?ctype=" + contenttype.Id.ToString());
                    }
                }
                catch
                {
                }

            }
            else if (change is SPChangeSite)
            {
                try
                {
                    SPChangeSite _change = (SPChangeSite)change;
                    changeinfo.objectTitle = site.ServerRelativeUrl;
                    changeinfo.objectUrl = site.ServerRelativeUrl;
                }
                catch
                {
                }
            }
            else if (change is SPChangeWeb)
            {
                try
                {
                    SPChangeWeb _change = (SPChangeWeb)change;
                    using (SPWeb web = site.OpenWeb(_change.Id))
                    {
                        changeinfo.objectTitle = web.Title;
                        changeinfo.objectUrl = web.ServerRelativeUrl;
                        changeinfo.user = GetChangeUser(change, web);
                    }
                }
                catch
                {
                    string hiddenObjectUrl = GetHiddenObjectUrl(change);
                    if (!string.IsNullOrEmpty(hiddenObjectUrl))
                    {
                        changeinfo.objectTitle = hiddenObjectUrl;
                        changeinfo.objectUrl = SPUrlUtility.CombineUrl(site.ServerRelativeUrl, hiddenObjectUrl);
                    }
                }
            }
            else if (change is SPChangeList)
            {
                try
                {
                    SPChangeList _change = (SPChangeList)change;
                    using (SPWeb web = site.OpenWeb(_change.WebId))
                    {
                        try
                        {
                            SPList list = web.Lists[_change.Id];
                            changeinfo.objectTitle = list.Title;
                            changeinfo.objectUrl = list.DefaultViewUrl;
                            changeinfo.user = GetChangeUser(change, list);
                        }
                        catch
                        {
                            string hiddenObjectUrl = GetHiddenObjectUrl(change);
                            if (!string.IsNullOrEmpty(hiddenObjectUrl))
                            {
                                changeinfo.objectTitle = hiddenObjectUrl;
                                changeinfo.objectUrl = SPUrlUtility.CombineUrl(site.ServerRelativeUrl, hiddenObjectUrl);
                            }
                        }
                    }
                }
                catch
                {
                    string hiddenObjectUrl = GetHiddenObjectUrl(change);
                    if (!string.IsNullOrEmpty(hiddenObjectUrl))
                    {
                        changeinfo.objectTitle = hiddenObjectUrl;
                        changeinfo.objectUrl = hiddenObjectUrl;
                    }
                }
            }
            else if (change is SPChangeItem)
            {
                try
                {
                    SPChangeItem _change = (SPChangeItem)change;
                    using (SPWeb web = site.OpenWeb(_change.WebId))
                    {
                        try
                        {
                            SPList list = web.Lists[_change.ListId];
                            SPListItem listitem = list.GetItemByUniqueId(_change.UniqueId);

                            if (!string.IsNullOrEmpty(listitem.Title))
                                changeinfo.objectTitle = listitem.Title;
                            else
                                changeinfo.objectTitle = listitem.Url;

                            changeinfo.objectUrl = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, listitem.Url);
                            changeinfo.user = GetChangeUser(change, listitem);
                        }
                        catch
                        {
                            string hiddenObjectUrl = GetHiddenObjectUrl(change);
                            if (!string.IsNullOrEmpty(hiddenObjectUrl))
                            {
                                changeinfo.objectTitle = SPUrlUtility.CombineUrl(site.ServerRelativeUrl, hiddenObjectUrl);
                                changeinfo.objectUrl = SPUrlUtility.CombineUrl(site.ServerRelativeUrl, hiddenObjectUrl);
                            }
                        }
                    }
                }
                catch
                {
                }
            }
            else if (change is SPChangeSecurityPolicy)
            {
                SPChangeSecurityPolicy _change = (SPChangeSecurityPolicy)change;
                changeinfo.objectTitle = site.ServerRelativeUrl;
                changeinfo.objectUrl = site.ServerRelativeUrl;
            }
            return changeinfo;
        }


    }
}
